package com.auxgroup.smarthome.inner.service;

import com.auxgroup.bridge.app.inner.vo.DeviceModelInfoVo;
import com.auxgroup.bridge.app.inner.vo.DeviceModelListVo;
import com.auxgroup.bridge.app.inner.vo.DeviceModelSimpleVo;
import com.auxgroup.smarthome.BeanUtils;
import com.auxgroup.smarthome.constant.cache.CachedConsant;
import com.auxgroup.smarthome.inner.dto.DeviceModelInfoDto;
import com.auxgroup.smarthome.inner.entity.DeviceModelInfoEntity;
import com.auxgroup.smarthome.inner.entity.DeviceSnModelMappingEntity;
import com.auxgroup.smarthome.inner.repo.DeviceModelInfoRepo;
import com.auxgroup.smarthome.inner.repo.DeviceModelInfoRepoSpec;
import com.auxgroup.smarthome.inner.repo.DeviceSnModelMappingEntityRepo;
import com.auxgroup.smarthome.redis.config.ObjectRedis;
import com.auxgroup.smarthome.syscode.BusinessCode;
import com.auxgroup.smarthome.syscode.Syscode;
import com.auxgroup.smarthome.utils.FileUtils;
import com.auxgroup.smarthome.utils.HttpClientUtil;
import com.auxgroup.smarthome.utils.PageUtils;
import com.auxgroup.smarthome.web.ApiResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * Created by niuGuangzhe on 2017/7/25.
 */
@Service
public class DeviceModelInfoService {

    private Logger log = LoggerFactory.getLogger(DeviceModelInfoService.class);

    @Autowired
    private DeviceModelInfoRepo deviceModelInfoRepo;

    @Autowired
    private DeviceSnModelMappingEntityRepo deviceSnModelMappingEntityRepo;

    @Autowired
    private ObjectRedis objectRedis;

    private final String PREFIX = CachedConsant.DEVICE_MODEL_PREFIX;

    @Value("${mes.mesUrl}")
    private String MES_URL;

    @Value("${mes.wmsUrl}")
    private String WMS_URL;

    @Value("${mes.errPath}")
    private String MES_ERROR_PATH;

    private String lCommonModelId = "2480e2de-5b6b-45c4-a023-765c29b6b09f";//柜机通用型号Id
    private String gCommonModelId = "340d46be-75c8-4018-81e1-4a72592cb403";//挂机通用型号Id

    /**
     * 分页查询型号信息
     *
     * @param modelName     设备型号
     * @param modelItemName 设备物料型号
     * @param page          页码
     * @param size          每页大小
     * @return 返回表当中相应的设备型号信息
     */
    public Page<DeviceModelInfoVo> getDevicesInfo(String modelName, String modelItemName, Integer page, Integer size) {
        //按照创建时间降序排列
        Sort sort = new Sort(Sort.Direction.DESC, "createdAt");
        Pageable pageable = new PageRequest(page, size, sort);
        Page<DeviceModelInfoEntity> deviceModelInfoEntities = deviceModelInfoRepo.findAll(DeviceModelInfoRepoSpec.findByModelAndModelItemAndStatus(modelName, modelItemName), pageable);
        return new PageUtils(DeviceModelInfoVo.class, deviceModelInfoEntities).buildVosPage();
    }

    /**
     * 根据型号名称查找型号信息
     *
     * @param model 型号名称
     * @return
     */
    public ApiResponse<DeviceModelInfoVo> getDeviceInfoByModel(String model) {
        Page<DeviceModelInfoEntity> deviceModelInfoEntities = deviceModelInfoRepo.findByModelAndTrashFalse(model, null);
        if (deviceModelInfoEntities.getContent().size() > 1) {
            return ApiResponse.prompt(Syscode.DEVICE_MODEL_SIZE_ERROR);
        }
        if (deviceModelInfoEntities.getContent().size() == 0) {
            return ApiResponse.prompt(Syscode.DEVICE_MODEL_NOT_EXIST);
        }
        return ApiResponse.ok(BeanUtils.copyAttrs(new DeviceModelInfoVo(), deviceModelInfoEntities.getContent().get(0)));
    }


    public ApiResponse<DeviceModelInfoVo> getDeviceInfoByModelItem(String modelItem) {
        List<DeviceModelInfoEntity> deviceModelInfoEntities = deviceModelInfoRepo.findByModelItemAndDeviceTypeAndTrashFalse(modelItem, 1);
        if (deviceModelInfoEntities.size() == 0) {
            return ApiResponse.prompt(BusinessCode.MODEL_ITEM_NOT_FOUND);
        }
        return ApiResponse.ok(BeanUtils.copyAttrs(new DeviceModelInfoVo(), deviceModelInfoEntities.get(0)));
    }

    /**
     * 根据主键查找型号信息
     *
     * @param modelId
     * @return
     */
    public ApiResponse<DeviceModelInfoVo> getDeviceInfoByModelId(String modelId) {
        DeviceModelInfoEntity deviceModelInfoEntity = deviceModelInfoRepo.findByModelIdAndTrashFalse(modelId);
        if (deviceModelInfoEntity == null) {
            return ApiResponse.prompt(Syscode.DEVICE_MODEL_NOT_EXIST);
        }
        DeviceModelInfoVo vo = BeanUtils.copyAttrs(new DeviceModelInfoVo(), deviceModelInfoEntity);
        return ApiResponse.ok(vo);
    }

    /**
     * 返回所有型号信息
     *
     * @return
     */
    public ApiResponse<List<DeviceModelSimpleVo>> getAllNewDeviceModel() {
        return ApiResponse.ok(deviceModelInfoRepo.getAllNewDeviceModel());
    }

    /**
     * 获取所有的型号列表
     * @return
     */
    public ApiResponse<List<DeviceModelListVo>> getAllModelInfo() {
        List<DeviceModelInfoEntity> deviceModelInfoEntityList = deviceModelInfoRepo.findAllByTrashFalse();
        List<DeviceModelListVo> deviceModelListVoList = deviceModelInfoEntityList.stream().map(deviceModelInfoEntity -> {
            DeviceModelListVo deviceModelListVo = new DeviceModelListVo();
            BeanUtils.copyAttrs(deviceModelListVo, deviceModelInfoEntity);
            return deviceModelListVo;
        }).collect(Collectors.toList());
        return ApiResponse.ok(deviceModelListVoList);
    }

    public boolean isExistsModelName(String model) {
        List<DeviceModelInfoEntity> existsDeviceModel = deviceModelInfoRepo.findByModelAndTrashFalse(model);
        if(existsDeviceModel.size() > 0) {
            return true;
        }
        return false;
    }

    /**
     * 添加设备信息的函数
     *
     * @param deviceModelInfoDto 型号信息的封装
     * @param model              型号
     * @return 添加是否成功
     */
    public ApiResponse addDeviceInfo(DeviceModelInfoDto deviceModelInfoDto, String model, String modelItem) {
//        Page<DeviceModelInfoEntity> beforeEntities = deviceModelInfoRepo.findDistinctByModelOrModelItemAndTrashFalse(model, modelItem, null);
//        if (beforeEntities.getContent().size() > 0) {
//            //要加入的实体在库中已经存在
//            return ApiResponse.prompt(Syscode.DEVICE_MODEL_EXIST);
//        }
        List<DeviceModelInfoEntity> existsDeviceModel = deviceModelInfoRepo.findByModelAndTrashFalse(deviceModelInfoDto.getModel());

        if(existsDeviceModel.size() > 0) {
            return ApiResponse.prompt(Syscode.DEVICE_MODEL_NAME_EXIST);
        }
        DeviceModelInfoEntity deviceModelInfoEntity = deviceModelInfoRepo.findByModelItem(modelItem);
        if(null != deviceModelInfoEntity) {
            if (!deviceModelInfoEntity.getTrash()) {
                return ApiResponse.prompt(Syscode.DEVICE_MODEL_ITEM_EXISTS);
            }
            deviceModelInfoEntity.createModelInfo(deviceModelInfoDto);
            deviceModelInfoRepo.save(deviceModelInfoEntity);
            //添加到redis当中缓存起来
            objectRedis.add(PREFIX + deviceModelInfoEntity.getModelId(), 60L, deviceModelInfoEntity);
            return ApiResponse.prompt(Syscode.SC_OK);
        }

        deviceModelInfoEntity = new DeviceModelInfoEntity();
        deviceModelInfoEntity.createModelInfo(deviceModelInfoDto);
        deviceModelInfoEntity.setModelItem(modelItem);
        deviceModelInfoRepo.save(deviceModelInfoEntity);
        //添加到redis当中缓存起来
        objectRedis.add(PREFIX + deviceModelInfoEntity.getModelId(), 60L, deviceModelInfoEntity);
        return ApiResponse.prompt(Syscode.SC_OK);
    }

    /**
     * 修改型号信息
     *
     * @param deviceModelInfoDto 型号信息的封装
     * @param modelId            型号主键
     * @return 修改是否成功
     */
    public ApiResponse updateDeviceInfo(DeviceModelInfoDto deviceModelInfoDto, String modelId) {
        //开始查找
        DeviceModelInfoEntity finalEntity = findDeviceModelEntity(modelId);
        if (finalEntity == null) {
            return ApiResponse.prompt(Syscode.DEVICE_MODEL_NOT_EXIST);
        }
        finalEntity = BeanUtils.copyAttrs(finalEntity, deviceModelInfoDto);
        finalEntity = deviceModelInfoRepo.save(finalEntity);
        //重新缓存对象
        objectRedis.add(PREFIX + finalEntity.getModelId(), 60L, finalEntity);
        return ApiResponse.prompt(Syscode.SC_OK);
    }

    /**
     * 删除型号信息
     *
     * @param modelId 设备型号主键
     * @return 刪除是否成功
     */
    public ApiResponse deleteDeviceInfo(String modelId) {
        int influencesColumns = deviceModelInfoRepo.logicallyDeleted(modelId);
        if (influencesColumns == 0) {
            return ApiResponse.prompt(Syscode.FAIL);
        }
        //成功之后删除设备缓存
        objectRedis.delete(PREFIX + modelId);
        return ApiResponse.prompt(Syscode.SC_OK);
    }

    /**
     * 根据sn获取设备型号相关信息
     *
     * @param sn
     * @return
     */
    public ApiResponse<DeviceModelInfoVo> findDeviceTypeBySn(String sn) {
        DeviceSnModelMappingEntity mappingEntity = deviceSnModelMappingEntityRepo.findBySn(sn);
        if (mappingEntity == null) {
            return ApiResponse.prompt(Syscode.DEVICE_MODEL_SN_MAPPING_NOT_EXIST);
        }
        Page<DeviceModelInfoEntity> entities = deviceModelInfoRepo.findByModelItemAndTrashFalse(mappingEntity.getModelItem(), null);
        //手动解析page，因为当前只可能包括一个实体类或者为空
        if (entities == null || entities.getContent().size() != 1) {
            //--begin modify by lixiaoxiao 20180402 sn如果合法,找不到型号,解析物料编码规则,指向通用型号,并记录日志
            String modelItem = mappingEntity.getModelItem();
            FileUtils.writeFile("/data/logs/sn-model.txt",
                    "sn:"+sn+";modelItem:"+mappingEntity.getModelItem()+"\r\n");
            if(modelItem.indexOf("/") > 0){
                //条码匹配规则
                return itemMatch(modelItem);
            }else{
                DeviceModelInfoEntity gEntity = deviceModelInfoRepo.findByModelIdAndTrashFalse(gCommonModelId);
                return ApiResponse.ok(BeanUtils.copyAttrs(new DeviceModelInfoVo(), gEntity));
            }
            //--end modify by lixiaoxiao 20180402 sn如果合法,找不到型号,解析物料编码规则,指向通用型号,并记录日志
        } else {
            DeviceModelInfoEntity entity = entities.getContent().get(0);
            DeviceModelInfoVo vo = new DeviceModelInfoVo();
            return ApiResponse.ok(BeanUtils.copyAttrs(vo, entity));
        }
    }

    /**
     * 返回关键字带有的物料信息
     */
    public ApiResponse<List<String>> findKeyModelItem(String keyword,int page,int size) {
        if (StringUtils.isBlank(keyword)) {
            return ApiResponse.ok(deviceSnModelMappingEntityRepo.catchAllModelItem(page,size));
        }
        return ApiResponse.ok(deviceSnModelMappingEntityRepo.findAllModeItemByKeyword(keyword + "%",page,size));
    }

    /**
     * 封装根据modelId返回型号信息
     *
     * @param modelId
     * @return
     */
    public DeviceModelInfoEntity findDeviceModelEntity(String modelId) {
        DeviceModelInfoEntity entity = objectRedis.get(PREFIX + modelId, DeviceModelInfoEntity.class);
        if (entity == null) {
            entity = deviceModelInfoRepo.findByModelIdAndTrashFalse(modelId);
            if (entity != null) {
                //加入缓存
                objectRedis.add(PREFIX + entity.getModelId(), 60L, entity);
                return entity;
            }
        }
        return entity;
    }

    public ApiResponse writeDataToDB(List<DeviceSnModelMappingEntity> dtos){
        deviceSnModelMappingEntityRepo.save(dtos);
        return ApiResponse.prompt(Syscode.SC_OK);
    }

    /**
     * 远程调用Mes接口并返回参数
     *
     * @param date
     * @param pageNumber
     * @param batchNumber
     * @return
     */
    private String getResultFromMes(String date, Integer pageNumber, Integer batchNumber) {
        Map params = new HashMap();
        params.put("dayTime", date);
        params.put("page", String.valueOf(pageNumber));
        params.put("size", String.valueOf(batchNumber));
        log.info("请求Mes数据：dateTime:{} , page:{} , size:{} ", date, pageNumber, batchNumber);
        return HttpClientUtil.httpRequest(MES_URL, null, params, HttpClientUtil.MethodType.METHOD_GET);
    }

    /**
     * 查询modelId与sn是否匹配
     * @param modelId
     * @return
     */
    public long countSnByModelId(String modelId, String sn) {
        return deviceModelInfoRepo.countSnByModelId(modelId, sn);
    }

    /**
     * 条码匹配规则 add by lixiaoxiao 20180421
     * @param modelItem
     * @return
     */
    private ApiResponse<DeviceModelInfoVo> itemMatch(String modelItem){
        String subModelItem = modelItem.substring(modelItem.indexOf("/")-1,modelItem.indexOf("/"));
        if("L".equals(subModelItem)){
            DeviceModelInfoEntity lEntity = deviceModelInfoRepo.findByModelIdAndTrashFalse(lCommonModelId);
            return ApiResponse.ok(BeanUtils.copyAttrs(new DeviceModelInfoVo(), lEntity));
        }else if("W".equals(subModelItem)){
            return ApiResponse.prompt(Syscode.DEVICE_MODEL_ITEM_W);
        }else{
            DeviceModelInfoEntity gEntity = deviceModelInfoRepo.findByModelIdAndTrashFalse(gCommonModelId);
            return ApiResponse.ok(BeanUtils.copyAttrs(new DeviceModelInfoVo(), gEntity));
        }
    }
}
